package com.huawei.java.alogrithm;

import com.huawei.java.datahandle.CSVReader;
import com.huawei.java.datahandle.ResultWriter;
import com.huawei.java.model.*;

import java.util.*;

public class AlgorithmHandler {
    public Graph graph;

    private List<Demand> demands;

    // 按照用户节点可以达到的边缘节点数量进行排序，能达到边缘节点数少的优先分配
    public TreeSet<ClientNode> clientNodeTreeSet = new TreeSet<>();

    public void process() {
        for (int i = 15; i < 18; i++) {
            int twoCost = processTwo(i);
            if (twoCost < ResultHandle.bestCost) {
                ResultHandle.bestResults = new TreeSet<>(ResultHandle.timestampResults);
                ResultHandle.timestampResults.clear();
                ResultHandle.bestCost = twoCost;
            }

            if (i >= 1) {
                for (int j = 1; j < 5; j++) {
//                    float i1 = i + 0.1f * j - 0.05f;
//                    twoCost = processTwo(i1);
//                    if (twoCost < ResultHandle.bestCost) {
//                        ResultHandle.bestResults = new TreeSet<>(ResultHandle.timestampResults);
//                        ResultHandle.timestampResults.clear();
//                        ResultHandle.bestCost = twoCost;
//                    }

                    float i1 = i + 0.2f * j;
                    twoCost = processTwo(i1);
                    if (twoCost < ResultHandle.bestCost) {
                        ResultHandle.bestResults = new TreeSet<>(ResultHandle.timestampResults);
                        ResultHandle.timestampResults.clear();
                        ResultHandle.bestCost = twoCost;
                    }
                }
            }
        }

        // int oneCost = processOne();
        // if (oneCost < ResultHandle.bestCost) {
        //     ResultHandle.bestResults = new TreeSet<>(ResultHandle.timestampResults);
        //     ResultHandle.timestampResults.clear();
        //     ResultHandle.bestCost = oneCost;
        // }

        System.out.println(ResultHandle.bestCost);
        ResultWriter.writeResult(ResultHandle.bestResults);
    }

    public int processOne() {
        initData();
        handleData(demands);
        AllocatedCollection.init(graph.getSiteNodes());
        //System.out.println(demands);
        handleUsedThresholdData();
        int size = demands.size();
        for (Demand demand : demands) {
            UsedThresholdAlgorithm usedThresholdAlgorithm = new UsedThresholdAlgorithm(graph, clientNodeTreeSet, demands);
            usedThresholdAlgorithm.process(demand);
            // 进行下一步处理，用权值均值算法
            WeightAlgorithm weightAlgorithm = new WeightAlgorithm(graph, clientNodeTreeSet);
            weightAlgorithm.process(demand);
            demand.setDistributionSuccess(true);
        }
        return ResultCompute.sort(size);
    }

    public int processTwo(float numDiv) {
        initData();
        handleData(demands);
        AllocatedCollection.init(graph.getSiteNodes());
        //System.out.println(demands);
        handleUsedThresholdData();
        int size = demands.size();
        FullDistributionAlgorithm fullDistributionAlgorithm = new FullDistributionAlgorithm(graph, clientNodeTreeSet, demands);
        fullDistributionAlgorithm.processCollection(numDiv);
        return ResultCompute.sort(size);
    }

    private void handleData(List<Demand> demands) {
        demands.sort((oneDemand, anotherDemand) -> {
            Map<String, Integer> oneDemandMap = oneDemand.getDemandMap();
            int oneTotalDemand = oneDemandMap.values().stream().mapToInt(Integer::intValue).sum();
            Map<String, Integer> anotherDemandMap = anotherDemand.getDemandMap();
            int antherTotalDemand = anotherDemandMap.values().stream().mapToInt(Integer::intValue).sum();
            return antherTotalDemand - oneTotalDemand;
        });
        int size = demands.size() / 10;
        for (int i = 0; i < 10; i++) {
            List<Demand> tempDemands = demands.subList(i * size, size * (i + 1));
            Collections.shuffle(tempDemands);
        }
        int ceil = (int) Math.ceil(demands.size() * 0.95);
        int availableNum = demands.size() - ceil;
        AllocatedCollection.setMaxListSize(availableNum + 1);
        graph.getSiteNodes().forEach(siteNode -> siteNode.setAvailableNum(availableNum));
    }

    private void handleUsedThresholdData() {
        clientNodeTreeSet.clear();
        clientNodeTreeSet.addAll(graph.getClientNodes());
    }

    private void initData() {
        graph = CSVReader.readQOSFile();
        CSVReader.readSiteBandwidthFile(graph);
        demands = CSVReader.readDemandFile();
        Map<ClientNode, List<SiteNode>> clientMap = graph.getClientMap();
        Map<SiteNode, List<ClientNode>> siteMap = graph.getSiteMap();
        for (ClientNode clientNode : graph.getClientNodes()) {
            clientNode.setValidSiteNodes(clientMap.get(clientNode));
        }
        List<SiteNode> siteNodes = graph.getSiteNodes();
        Iterator<SiteNode> iterator = siteNodes.iterator();
        while (iterator.hasNext()) {
            SiteNode siteNode = iterator.next();
            siteNode.setValidClient(siteMap.get(siteNode));
            if (siteNode.getValidClient() == null) {
                iterator.remove();
            }
        }
        siteNodes.sort((oneSite, anotherSite) -> anotherSite.getValidClient().size() - oneSite.getValidClient().size());
        ResultWriter.deleteResultFile();
        ResultCompute.init();
    }
}
